package com.bookbuf.social.share.content.media.image.util;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.os.StatFs;
import android.text.TextUtils;
import android.util.Log;

import com.bookbuf.social.secure.AesHelper;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Arrays;
import java.util.Comparator;

/**
 * Created by robert on 16/7/4.
 */
public class BitmapUtils {
	public static final String FOLDER = "/social_cache/";
	public static String PATH = "/mnt/sdcard/";
	private static final int MB = (int) Math.pow (2, 20);
	public static final int MAX_BITMAP_SIZE = 3 * MB;
	private static final int FREE_SD_SPACE = 40;
	private static final int CACHE_SIZE = 10;
	public static int MAX_WIDTH;
	public static int MAX_HEIGHT;

	public BitmapUtils () {
	}

	public static void init () {
		if (Util.isSdCardWrittable ()) {
			PATH = Environment.getExternalStorageDirectory ().getPath () + FOLDER;
		} else {
			PATH = Environment.getDataDirectory ().getPath () + FOLDER;
		}
		File file = new File (PATH);
		if (!file.exists ()) {
			file.mkdir ();
		}
		try {
			remove40PercentCache (PATH);
			file = null;
		} catch (Exception var3) {
			Log.d ("BitmapUtils", "清除缓存抛出异常 ： " + var3.toString ());
		}
		System.gc ();
	}

	public static BitmapFactory.Options getScaleBitmapOptions (String path, int destWidth, int destHeight) {
		InputStream inputStream = getBitmapStream (path);
		if (inputStream == null) {
			return null;
		} else {
			BitmapFactory.Options options = new BitmapFactory.Options ();
			options.inJustDecodeBounds = true;
			try {
				BitmapFactory.decodeStream (inputStream, null, options);
				int height = (int) Math.ceil ((double) options.outHeight / destHeight);
				int width = (int) Math.ceil ((double) (options.outWidth / destWidth));
				if (height > 1 && width > 1) {
					if (height > width) {
						options.inSampleSize = height;
					} else {
						options.inSampleSize = width;
					}
				}
				options.inJustDecodeBounds = false;
			} catch (Exception e) {
				e.printStackTrace ();
			}
			closeInputStream (inputStream);
			return options;
		}
	}

	public static InputStream getBitmapStream (String filePath) {
		FileInputStream inputStream = null;
		try {
			inputStream = new FileInputStream (new File (getFileName (filePath)));
		} catch (FileNotFoundException e) {
			e.printStackTrace ();
		}
		try {
			if (inputStream == null || inputStream.available () <= 0) {
				InputStream urlStream = (new URL (filePath)).openStream ();
				saveInputStream (getFileName (filePath), urlStream);
				inputStream = new FileInputStream (new File (getFileName (filePath)));
			}
		} catch (IOException e) {
			e.printStackTrace ();
		}
		return inputStream;
	}

	public static void saveInputStream (String fileName, InputStream inputStream) {
		FileOutputStream outputStream = null;

		try {
			outputStream = new FileOutputStream (new File (fileName));
			byte[] cache = new byte[1024];
			int byteCount;
			while ((byteCount = inputStream.read (cache)) != -1) {
				outputStream.write (cache, 0, byteCount);
			}
			outputStream.flush ();
		} catch (FileNotFoundException e) {
			e.printStackTrace ();
		} catch (IOException e) {
			e.printStackTrace ();
		} finally {
			if (outputStream != null) {
				try {
					outputStream.close ();
				} catch (IOException e) {
					e.printStackTrace ();
				}
			}
		}
	}

	public static Bitmap loadImage (String filePath, int destWidth, int destHeight) {
		if (TextUtils.isEmpty (filePath)) {
			return null;
		} else {
			Bitmap bitmap = null;
			InputStream inputStream = null;

			try {
				inputStream = getBitmapStream (filePath);
				bitmap = BitmapFactory.decodeStream (inputStream, null, getScaleBitmapOptions (filePath, destWidth, destHeight));
			} catch (Exception e) {
				e.printStackTrace ();
			} finally {
				closeInputStream (inputStream);
			}
			return bitmap;
		}
	}

	public static boolean isFileExist (String filePath) {
		if (TextUtils.isEmpty (filePath)) {
			return false;
		} else {
			File file = new File (getFileName (filePath));
			return file.getAbsoluteFile ().exists ();
		}
	}

	public static boolean isNeedScale (String filePath, int maxLength) {
		File file = new File (getFileName (filePath));
		return file.exists () && file.length () >= (long) maxLength;
	}

	public static Bitmap getBitmapFromFile (String filePath) {
		InputStream inputStream = getBitmapStream (filePath);
		if (inputStream == null) {
			return null;
		} else {
			Bitmap bitmap = BitmapFactory.decodeStream (inputStream);
			closeInputStream (inputStream);
			return bitmap;
		}
	}

	public static Bitmap getBitmapFromFile (String filePath, int destWidth, int destHeight) {
		InputStream inputStream = getBitmapStream (filePath);
		if (inputStream == null) {
			return null;
		} else {
			Bitmap var4 = BitmapFactory.decodeStream (inputStream, null, getScaleBitmapOptions (filePath, destWidth, destHeight));
			closeInputStream (inputStream);
			return var4;
		}
	}

	public static void saveBitmap (String filePath, Bitmap bitmap) {
		try {
			BufferedOutputStream var2 = new BufferedOutputStream (new FileOutputStream (getFileName (filePath)));
			byte quality = 100;
			if (bitmap.getRowBytes () * bitmap.getHeight () > MAX_BITMAP_SIZE) {
				quality = 80;
			}

			bitmap.compress (Bitmap.CompressFormat.PNG, quality, var2);
			var2.flush ();
			var2.close ();
		} catch (Exception var4) {
			var4.printStackTrace ();
		}
	}

	public static void closeInputStream (InputStream inputStream) {
		if (inputStream != null) {
			try {
				inputStream.close ();
			} catch (Exception e) {
				Log.d ("BitmapUtils", e.toString ());
			}
		}
	}

	public static String getFileName (String filePath) {
		if (TextUtils.isEmpty (filePath)) {
			return "";
		} else {
			String path = filePath;
			if (filePath.startsWith ("http://") || filePath.startsWith ("https://")) {
				path = PATH + AesHelper.md5 (filePath);
			}
			return path;
		}
	}

	public static byte[] bitmap2Bytes (Bitmap bitmap) {
		ByteArrayOutputStream outputStream = null;
		if (bitmap != null && !bitmap.isRecycled ()) {
			try {
				outputStream = new ByteArrayOutputStream ();
				int size = bitmap.getRowBytes () * bitmap.getHeight ();
				int quality = 100;
				if (size > MAX_BITMAP_SIZE) {
					quality = (int) (MAX_BITMAP_SIZE / (float) size * (float) quality);
				}

				Log.d ("BitmapUtil", "compress quality:" + quality);
				bitmap.compress (Bitmap.CompressFormat.JPEG, quality, outputStream);
				return outputStream.toByteArray ();
			} catch (Exception e) {
				Log.e ("BitmapUtils", e.toString ());
			} finally {
				if (outputStream != null) {
					try {
						outputStream.close ();
					} catch (IOException e) {
						e.printStackTrace ();
					}
				}

			}
			return null;
		} else {
			Log.d ("BitmapUtils", "bitmap2Bytes  ==> bitmap == null or bitmap.isRecycled()");
			return null;
		}
	}

	public static int calculateInSampleSize (BitmapFactory.Options options, int maxWidth, int maxHeight) {
		int height = options.outHeight;
		int width = options.outWidth;
		int rate = 1;
		if (height > maxHeight || width > maxWidth) {
			int tmp = height / 2;
			for (int tmpWidth = width / 2; tmp / rate > maxHeight && tmpWidth / rate > maxWidth; rate *= 2) {
				;
			}
		}
		return rate;
	}

	public static BitmapFactory.Options getBitmapOptions (byte[] bytes) {
		BitmapFactory.Options options = new BitmapFactory.Options ();
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeByteArray (bytes, 0, bytes.length, options);
		int width = (int) Math.ceil ((double) (options.outWidth / MAX_WIDTH));
		int height = (int) Math.ceil ((double) (options.outHeight / MAX_HEIGHT));
		if (height > 1 && width > 1) {
			if (height > width) {
				options.inSampleSize = height;
			} else {
				options.inSampleSize = width;
			}
		} else if (height > 2) {
			options.inSampleSize = height;
		} else if (width > 2) {
			options.inSampleSize = width;
		}
		options.inJustDecodeBounds = false;
		return options;
	}

	private static int freeSpaceOnSd () {
		StatFs statFs = new StatFs (Environment.getExternalStorageDirectory ().getPath ());
		double v = (double) statFs.getAvailableBlocks () * (double) statFs.getBlockSize () / MB;
		return (int) v;
	}


	private static void remove40PercentCache (String filePath) {
		File file = new File (filePath);
		File[] listFiles = file.listFiles ();
		if (listFiles.length != 0) {
			int totalLength = 0;

			int i;
			for (i = 0; i < listFiles.length; ++i) {
				totalLength = (int) ((long) totalLength + listFiles[i].length ());
			}

			if (totalLength > CACHE_SIZE * MB || FREE_SD_SPACE > freeSpaceOnSd ()) {
				i = (int) (0.4D * (double) listFiles.length + 1.0D);
				Arrays.sort (listFiles, new FileLastModifySort ());

				for (int var5 = 0; var5 < i; ++var5) {
					listFiles[var5].delete ();
				}
			}

		}
	}

	public static void cleanCache () {
		init ();
	}


	public static byte[] compressBitmap (byte[] bytes, int maxSize) {
		boolean breakIt = false;
		if (bytes != null && bytes.length >= maxSize) {
			ByteArrayOutputStream outputStream = new ByteArrayOutputStream ();
			Bitmap bitmap = BitmapFactory.decodeByteArray (bytes, 0, bytes.length);
			int cacheSize = 1;
			double compressRate = 1.0D;

			while (true) {
				while (!breakIt && cacheSize <= CACHE_SIZE) {
					compressRate = Math.pow (0.8D, (double) cacheSize);
					int quality = (int) (100.0D * compressRate);
					Log.d ("BitmapUtils", "quality = " + quality);
					bitmap.compress (Bitmap.CompressFormat.JPEG, quality, outputStream);
					Log.d ("BitmapUtils", "WeiXin Thumb Size = " + outputStream.toByteArray ().length / 1024 + " KB");
					if (outputStream != null && outputStream.size () < maxSize) {
						breakIt = true;
					} else {
						outputStream.reset ();
						++cacheSize;
					}
				}

				if (outputStream != null) {
					byte[] toByteArray = outputStream.toByteArray ();
					if (!bitmap.isRecycled ()) {
						bitmap.recycle ();
					}

					if (toByteArray != null && toByteArray.length <= 0) {
						Log.e ("BitmapUtils", "### 您的原始图片太大,导致缩略图压缩过后还大于32KB,请将分享到微信的图片进行适当缩小.");
					}

					return toByteArray;
				}
				break;
			}
		}

		return bytes;
	}

	public static Bitmap createThumb (Bitmap bitmap, float size) {
		Bitmap ret = null;
		if (bitmap != null && !bitmap.isRecycled ()) {
			int width = bitmap.getWidth ();
			int height = bitmap.getHeight ();
			float thumbRate = 1.0F;
			if (width < 200 || height < 200) {
				if (width < height) {
					thumbRate = size / (float) width;
				} else {
					thumbRate = size / (float) height;
				}
			}

			ret = Bitmap.createScaledBitmap (bitmap, (int) (thumbRate * (float) width), (int) (thumbRate * (float) height), true);
			if (ret == null) {
				ret = bitmap;
			}
		}

		return ret;
	}

	static {
		init ();
		MAX_WIDTH = 768;
		MAX_HEIGHT = 1024;
	}

	private static class FileLastModifySort implements Comparator<File> {
		private FileLastModifySort () {
		}

		public int compare (File prev, File next) {
			return prev.lastModified () > next.lastModified () ? 1 : (prev.lastModified () == next.lastModified () ? 0 : -1);
		}
	}
}